
/*本代码仅仅用于学习，想看具体的注释去copy.c文件看，有问题可以发送信息到qq邮箱：3560944847@qq.com*/



#include <stm32f4xx.h>
#include <includes.h>
#include <stdio.h>
#include <string.h>

#include <lvgl.h>
#include <lv_port_disp.h>
#include <lv_port_indev.h>
#include <lv_demo_widgets.h>
#include <touch.h>

#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>
#include <event_groups.h>
#include <queue.h>
#include <timers.h>

#include <ui.h>

#define QUEUE_SIZE 4

LV_FONT_DECLARE(my_font);

volatile uint8_t g_lock_operating = 0;  // 锁操作状态标志

// 添加卡相关宏定义
#define CARD_NUM         5       // 最大注册卡数量
#define CARD_SIZE        6       // 每张卡存储大小(前缀+5字节卡号)
#define CARD_ADDR        0x00000 // 存储起始地址


//添加密码相关宏定义
#define PASSWORD_ADDR    0x01000 // 密码存储地址（避免与卡号冲突）
#define PASSWORD_LENGTH  6       // 密码长度
#define DEFAULT_PASSWORD "000000" // 默认密码
//现在密码888888

//添加修改手机号码相关宏
// 添加手机号码相关宏定义
#define PHONE_NUMBER_ADDR 0x02000  // 手机号码存储地址
#define PHONE_LENGTH      11       // 手机号码长度
#define DEFAULT_PHONE     "15207640967" // 默认手机号码

// 全局变量
char current_phone_number[PHONE_LENGTH + 1]; // 当前手机号码



//// 模式定义
//#define MODE_VERIFY      0       // 验证模式
//#define MODE_REGISTER    1       // 注册模式
//#define MODE_CLEAR       2       // 清空模式

//指纹模块的变量
SysPara AS608Para;//指纹模块AS608参数
u16 ValidN;//模块内有效指纹个数

// 全局变量
volatile uint8_t g_mode = MODE_VERIFY;   // 默认验证模式
uint8_t current_password[PASSWORD_LENGTH + 1]; // 当前密码缓冲区
uint8_t card_type[2];           // 卡类型缓冲区
uint8_t card_id[6];             // 卡号缓冲区(包含校验位)
uint8_t record_card[6];         // 存储的卡号缓冲区
	
TaskHandle_t app_task_init_handle 			= NULL;
TaskHandle_t app_task_1_handle		= NULL;
TaskHandle_t app_task_2_handle			= NULL;
TaskHandle_t app_task_3_handle			= NULL;
TaskHandle_t app_task_4_handle			= NULL;
TaskHandle_t app_task_5_handle			= NULL;
TaskHandle_t app_task_6_handle			= NULL;


//消息队列的句柄
QueueHandle_t usart_queue = NULL;

//二值信号量句柄
SemaphoreHandle_t  lock_433m_sem_exit;

//互斥锁句柄
SemaphoreHandle_t oled_mutex; //OLED显示互斥锁
SemaphoreHandle_t vibrate_mutex; //震动传感器互斥锁



void app_task_init(void *pvParameters);
void app_task_1(void *pvParameters);
void app_task_2(void *pvParameters);
void app_task_3(void *pvParameters);
void app_task_4(void *pvParameters);
void app_task_5(void *pvParameters);
void app_task_6(void *pvParameters);

// 添加卡模式设置函数
void set_card_mode(uint8_t mode) {
    taskENTER_CRITICAL();
    g_mode = mode;
    taskEXIT_CRITICAL();
}

//指纹

//刷指纹
//刷指纹 - 修改为返回验证结果
uint8_t press_FR(void)
{
    SearchResult seach;
    u8 ensure;
    char str[64];
    
    ensure = PS_GetImage();
    if(ensure == 0x00) // 获取图像成功 
    {    
        printf("获取图像成功\r\n");
        ensure = PS_GenChar(CharBuffer1);
        if(ensure == 0x00) // 生成特征成功
        {        
            printf("生成特征成功\r\n");
            ensure = PS_HighSpeedSearch(CharBuffer1, 0, AS608Para.PS_max, &seach);
            if(ensure == 0x00) // 搜索成功
            {                
                printf("搜索成功\r\n");
                sprintf(str, "确有此人,ID:%d  匹配得分:%d", seach.pageID, seach.mathscore);
                printf("%s\r\n", str);
                
                // 验证成功，返回1
                return 1;
            }
            else 
            {
                printf("搜索失败\r\n");
                return 0;
            }        
        }
        else
        {
            printf("生成特征失败\r\n");
            return 0;
        }        
    }
    else if(ensure == 0x02) 
    {
        // 传感器上没有手指，不算是错误，返回2表示等待手指
        return 2;
    }
    else
    {
        printf("获取图像失败: %s\r\n", EnsureMessage(ensure));
        return 0;
    }
    
    delay_ms(600);
    return 0;
}

// 改进的指纹注册函数
void register_FR(u16 pageID)
{
    u8 ensure;
    u8 processnum = 0;
    u8 retry_count = 0;
    
    printf("开始注册指纹，ID: %d\n", pageID);
    
    while(1)
    {
        switch(processnum)
        {
            case 0: // 第一步：第一次按压
                retry_count++;
                printf("请第一次按压指纹...\n");
                
                ensure = PS_GetImage();
                if(ensure == 0x00) 
                {
                    ensure = PS_GenChar(CharBuffer1); // 生成特征
                    if(ensure == 0x00)
                    {
                        printf("第一次按压成功\n");
                        retry_count = 0;
                        processnum = 1; // 跳到第二步
                    }
                    else 
                    {
                        printf("第一次生成特征失败: %s\n", EnsureMessage(ensure));
                    }
                }
                else 
                {
                    printf("第一次获取图像失败: %s\n", EnsureMessage(ensure));
                }
                break;
            
            case 1: // 第二步：第二次按压
                retry_count++;
                printf("请第二次按压指纹...\n");
                
                ensure = PS_GetImage();
                if(ensure == 0x00) 
                {
                    ensure = PS_GenChar(CharBuffer2); // 生成特征
                    if(ensure == 0x00)
                    {
                        printf("第二次按压成功\n");
                        retry_count = 0;
                        processnum = 2; // 跳到第三步
                    }
                    else 
                    {
                        printf("第二次生成特征失败: %s\n", EnsureMessage(ensure));
                    }
                }
                else 
                {
                    printf("第二次获取图像失败: %s\n", EnsureMessage(ensure));
                }
                break;

            case 2: // 第三步：对比两次指纹
                printf("对比两次指纹...\n");
                
                ensure = PS_Match();
                if(ensure == 0x00) 
                {
                    printf("对比成功，两次指纹一致\n");
                    processnum = 3; // 跳到第四步
                }
                else 
                {
                    printf("对比失败，请重新录入指纹: %s\n", EnsureMessage(ensure));
                    retry_count = 0;
                    processnum = 0; // 跳回第一步
                }
                delay_ms(1200);
                break;

            case 3: // 第四步：生成指纹模板
                printf("生成指纹模板...\n");
                
                ensure = PS_RegModel();
                if(ensure == 0x00) 
                {
                    printf("生成指纹模板成功\n");
                    processnum = 4; // 跳到第五步
                }
                else 
                {
                    printf("生成模板失败: %s\n", EnsureMessage(ensure));
                    processnum = 0; // 跳回第一步
                }
                delay_ms(1200);
                break;
                
            case 4: // 第五步：存储指纹
                printf("存储指纹到ID: %d\n", pageID);
                
                // 检查ID是否有效
                if(pageID >= AS608Para.PS_max)
                {
                    printf("ID超出范围！最大ID: %d\n", AS608Para.PS_max - 1);
                    return;
                }
                
                ensure = PS_StoreChar(CharBuffer1, pageID); // 储存模板
                if(ensure == 0x00) 
                {            
                    printf("指纹注册成功！ID: %d\n", pageID);
                    
                    // 读取并显示指纹库信息
                    PS_ValidTempleteNum(&ValidN);
                    printf("指纹库剩余容量: %d\n", AS608Para.PS_max - ValidN);
                    
                    return;
                }
                else 
                {
                    printf("指纹存储失败: %s\n", EnsureMessage(ensure));
                    processnum = 0; // 跳回第一步
                }
                break;
        }
        
        // 超时处理：超过10次重试则退出
        if(retry_count >= 10)
        {
            printf("操作超时，注册中止\n");
            return;
        }
        
        delay_ms(400);
    }
}


// 简化的删除指纹函数（只删除指定ID）
void delete_single_FR(u16 pageID)
{
    u8 ensure;
    
    printf("删除指纹ID: %d\n", pageID);
    
    // 更可靠的验证方法：直接尝试读取模板
    printf("验证指纹ID %d 是否存在...\n", pageID);
    
    // 方法1：使用PS_ReadNotebook读取笔记本信息（如果支持）
    // 方法2：直接尝试删除，根据返回结果判断
    
    ensure = PS_DeletChar(pageID, 1);  // 直接尝试删除
    if(ensure == 0x00)
    {
        printf("删除指纹ID %d 成功\n", pageID);
    }
    else if(ensure == 0x01)  // 根据AS608协议，0x01通常表示地址错误或模板不存在
    {
        printf("指纹ID %d 不存在，无法删除\n", pageID);
    }
    else
    {
        printf("删除指纹失败: %s\n", EnsureMessage(ensure));
    }	
    
    // 更新指纹库信息
    if(PS_ValidTempleteNum(&ValidN) == 0x00)
    {
        printf("当前指纹数量: %d\n", ValidN);
    }
}

// 清空所有指纹
void clear_all_FR(void)
{
    u8 ensure;
    u16 valid_num;
    
    printf("准备清空所有指纹...\n");
    
    // 先获取当前指纹数量
    ensure = PS_ValidTempleteNum(&valid_num);
    if(ensure == 0x00 && valid_num > 0)
    {
        printf("当前有 %d 个指纹，确认清空吗？\n", valid_num);
        printf("按按键3确认清空，其他按键取消\n");
        
        // 等待用户确认（这里简化处理，实际可以添加确认逻辑）
        delay_ms(3000);
        
        ensure = PS_Empty();
        if(ensure == 0x00)
        {
            printf("清空指纹库成功\n");
        }
        else
        {
            printf("清空指纹库失败: %s\n", EnsureMessage(ensure));
        }
    }
    else if(valid_num == 0)
    {
        printf("指纹库已经是空的\n");
    }
    else
    {
        printf("读取指纹数量失败: %s\n", EnsureMessage(ensure));
    }
}

// 执行开锁操作函数
void execute_unlock_procedure(void)
{
	
	 // 检查是否正在执行开锁操作
    if(g_lock_operating) {
        printf("开锁操作正在进行中，跳过本次操作\r\n");
        return;
    }
    
    // 设置开锁状态
    g_lock_operating = 1;
    // 蜂鸣器提示
    BEEP_ON;
    delay_ms(100);
    BEEP_OFF;
    
    // 开锁
    lock_on();
    delay_ms(1500);
    lock_off();
    
    // 舵机控制
    sg90_angle_set(0);    // 先复位到0度
    delay_ms(500);
    sg90_angle_set(140);  // 转动到140度
    delay_ms(500);
	
	  // 清除开锁状态
    g_lock_operating = 0;
    
    printf("开锁操作完成\r\n");
}

void safe_unlock(void)
{
    static uint32_t last_unlock_time = 0;
    uint32_t current_time = xTaskGetTickCount();
    
    // 2秒内不重复开锁
    if((current_time - last_unlock_time) < pdMS_TO_TICKS(2000)) {
        printf("开锁操作过于频繁，忽略本次操作\r\n");
        return;
    }
    
    last_unlock_time = current_time;
    execute_unlock_procedure();
}

////////////////////////////////////////////

// 密码管理函数
void password_init(void)
{
	uint8_t flash_data[PASSWORD_LENGTH];
    // 读取密码，如果没有设置则使用默认密码
    w25q128_read_data(PASSWORD_ADDR, current_password, PASSWORD_LENGTH);
	
	printf("Flash原始数据: ");
    for(int i = 0; i < PASSWORD_LENGTH; i++) {
        printf("%02X ", flash_data[i]);
    }
    printf("\r\n");
	 // 确保字符串结束符
    current_password[PASSWORD_LENGTH] = '\0';
    
    // 检查是否是第一次使用（全0xFF或无效数据）
    uint8_t is_first_use = 1;
      for(int i = 0; i < PASSWORD_LENGTH; i++) {
        if(current_password[i] != 0xFF && current_password[i] >= '0' && current_password[i] <= '9') {
            is_first_use = 0;
            break;
        }
    }
    
    if(is_first_use) {
        // 设置默认密码
        memcpy(current_password, DEFAULT_PASSWORD, PASSWORD_LENGTH);
		 current_password[PASSWORD_LENGTH] = '\0';
        // 保存到Flash
        w25q128_write_page(PASSWORD_ADDR, current_password, PASSWORD_LENGTH);
        printf("初始化默认密码: %s\r\n", DEFAULT_PASSWORD);
    } else {
        // 确保读取的数据是有效的ASCII字符串
        for(int i = 0; i < PASSWORD_LENGTH; i++) {
            if(current_password[i] < '0' || current_password[i] > '9') {
                current_password[i] = '0'; // 替换为有效数字
            }
        }
        current_password[PASSWORD_LENGTH] = '\0';
        printf("读取密码: %s\r\n", current_password);
    }
}

//核实密码
uint8_t verify_password(const char* input_password)
{
    return (memcmp(input_password, current_password, PASSWORD_LENGTH) == 0);
}

//更换密码
uint8_t change_password(const char* old_password, const char* new_password)
{
    if(verify_password(old_password)) {
        // 验证旧密码成功
        if(strlen(new_password) != PASSWORD_LENGTH) {
            printf("新密码长度错误！\r\n");
            return 0;
        }
        
        // 擦除扇区
        w25q128_erase_sector(PASSWORD_ADDR);
        delay_ms(50);
        
        // 写入新密码
        w25q128_write_page(PASSWORD_ADDR, (uint8_t*)new_password, PASSWORD_LENGTH);
        
        // 更新当前密码
        memcpy(current_password, new_password, PASSWORD_LENGTH);
        current_password[PASSWORD_LENGTH] = '\0';
        
        printf("密码修改成功: %s\r\n", new_password);
        return 1;
    } else {
        printf("旧密码验证失败！\r\n");
        return 0;
    }
}

//获得密码
void get_password_display(char* display_buf)
{
    memcpy(display_buf, current_password, PASSWORD_LENGTH);
    display_buf[PASSWORD_LENGTH] = '\0';
}

//////////////////////////////////////////////////////////////////////////

// 验证手机号码函数
// 手机号码初始化
void phone_number_init(void)
{
    uint8_t flash_data[PHONE_LENGTH];
    
    // 读取手机号码
    w25q128_read_data(PHONE_NUMBER_ADDR, (uint8_t*)current_phone_number, PHONE_LENGTH);
    current_phone_number[PHONE_LENGTH] = '\0';
    
    // 检查是否是第一次使用
    uint8_t is_first_use = 1;
    for(int i = 0; i < PHONE_LENGTH; i++) {
        if(current_phone_number[i] != 0xFF && current_phone_number[i] >= '0' && current_phone_number[i] <= '9') {
            is_first_use = 0;
            break;
        }
    }
    
    if(is_first_use) {
        // 设置默认手机号码
        memcpy(current_phone_number, DEFAULT_PHONE, PHONE_LENGTH);
        current_phone_number[PHONE_LENGTH] = '\0';
        // 保存到Flash
        w25q128_write_page(PHONE_NUMBER_ADDR, (uint8_t*)current_phone_number, PHONE_LENGTH);
        printf("初始化默认手机号码: %s\r\n", DEFAULT_PHONE);
    } else {
        printf("读取手机号码: %s\r\n", current_phone_number);
    }
}

// 验证手机号码
uint8_t verify_phone_number(const char* phone_number)
{
    return (memcmp(phone_number, current_phone_number, PHONE_LENGTH) == 0);
}

// 修改手机号码
uint8_t change_phone_number(const char* new_phone_number)
{
    if(strlen(new_phone_number) != PHONE_LENGTH) {
        printf("手机号码长度错误！\r\n");
        return 0;
    }
    
    // 擦除扇区
    w25q128_erase_sector(PHONE_NUMBER_ADDR);
    delay_ms(50);
    
    // 写入新手机号码
    w25q128_write_page(PHONE_NUMBER_ADDR, (uint8_t*)new_phone_number, PHONE_LENGTH);
    
    // 更新当前手机号码
    memcpy(current_phone_number, new_phone_number, PHONE_LENGTH);
    current_phone_number[PHONE_LENGTH] = '\0';
    
    printf("手机号码修改成功: %s\r\n", new_phone_number);
    return 1;
}

// 获取当前手机号码
void get_current_phone_number(char* phone_buf)
{
    memcpy(phone_buf, current_phone_number, PHONE_LENGTH);
    phone_buf[PHONE_LENGTH] = '\0';
}

/////////////////////////////////////////////////////////////////////////
//获得所有卡号
void get_all_cards_display(char* display_buf, uint16_t buf_size)
{
    uint8_t record_card[6];
    uint8_t card_count = 0;
    
    // 清空显示缓冲区
    display_buf[0] = '\0';
    
    for(uint8_t i = 0; i < CARD_NUM; i++) {
        w25q128_read_data(CARD_ADDR + i * CARD_SIZE, record_card, CARD_SIZE);
        
        if(record_card[0] == 0x55) {
            // 格式化卡号
            char card_str[20];
            snprintf(card_str, sizeof(card_str), "Card %d: %02X%02X%02X%02X%02X\n", 
                     card_count + 1, 
                     record_card[1], record_card[2], record_card[3], 
                     record_card[4], record_card[5]);
            
            // 检查缓冲区是否足够
            if(strlen(display_buf) + strlen(card_str) < buf_size - 1) {
                strcat(display_buf, card_str);
                card_count++;
            } else {
                strcat(display_buf, "...\n(More cards)");
                break;
            }
        } else {
            break; // 遇到空位置，提前结束
        }
    }
    
    if(card_count == 0) {
        strcpy(display_buf, "No cards registered");
    }
}



int main()
{
	//中断优先级分组 4:0
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	led_init();
	beep_init();
	key_init();
	lock_init();
	uart1_init (9600);
//	uart2_init(9600);
	usart2_init(57600);
	
	
	/* 创建 app_task_init任务 */
	xTaskCreate((TaskFunction_t)app_task_init,			/* 任务入口函数 */
				(const char *)"app_task_init",			/* 任务名字 */
				(uint16_t)1024,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)5,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_init_handle); /* 任务控制块指针 */

	/* 开启任务调度 */
	vTaskStartScheduler();

	while (1);
}

void app_task_init(void *pvParameters)
{
	printf("app_task_init start!\r\n");
	
	oled_init();
	esp8266_init(115200);
	get_3days_weather();
	show_weather(0);
	ia_init();
	sr04_init();
	spi1_init ();
	MF522_Init();  // 初始化RC522模块
	sg90_init();
	rtc_init();
	vibrate_buzzer_init();
	lock_433m_init();
	// 初始化密码系统
    password_init();
	//初始化手机号码
	phone_number_init();
	
	//初始化指纹相关
	PS_StaGPIO_Init();
	
	//握手
	while(PS_HandShake(&AS608Addr))//与AS608模块握手
	{
		delay_ms(400);
		printf("尝试连接模块\r\n");
		delay_ms(800);
	}
	printf("握手成功\r\n");
	
	    // 立即读取系统参数
    printf("读取系统参数...\r\n");
    u8 ensure = PS_ReadSysPara(&AS608Para);
    if(ensure == 0x00)
    {
        printf("系统参数读取成功！\r\n");
        printf("指纹库最大容量: %d\r\n", AS608Para.PS_max);
        printf("安全等级: %d\r\n", AS608Para.PS_level);
        printf("波特率: %d\r\n", AS608Para.PS_N * 9600);
    }
    else
    {
        printf("系统参数读取失败: %s\r\n", EnsureMessage(ensure));
        // 设置默认值防止崩溃
        AS608Para.PS_max = 300; // 默认300个指纹容量
        printf("使用默认容量: %d\r\n", AS608Para.PS_max);
    }

    // 读取指纹数量
    ensure = PS_ValidTempleteNum(&ValidN);
    if(ensure == 0x00)
    {
        printf("当前指纹数量: %d\r\n", ValidN);
    }


	
	
	//创建消息队列
	usart_queue = xQueueCreate(QUEUE_SIZE,sizeof(usart_rx_buf));
	
	//创建二值信号量
	lock_433m_sem_exit = xSemaphoreCreateBinary();//初值0
	
	//创建互斥锁
	oled_mutex = xSemaphoreCreateMutex();
	vibrate_mutex = xSemaphoreCreateMutex();
	
	/* 创建用到的任务 */
	taskENTER_CRITICAL();

	xTaskCreate((TaskFunction_t)app_task_1,			/* 任务入口函数 */
				(const char *)"app_task_1",			/* 任务名字 */
				(uint16_t)512,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)6,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_1_handle); /* 任务控制块指针 */
				
	xTaskCreate((TaskFunction_t)app_task_2,			/* 任务入口函数 */
				(const char *)"app_task_2",			/* 任务名字 */
				(uint16_t)512,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)6,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_2_handle); /* 任务控制块指针 */
				
	xTaskCreate((TaskFunction_t)app_task_3,			/* 任务入口函数 */
				(const char *)"app_task_3",			/* 任务名字 */
				(uint16_t)512,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)6,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_3_handle); /* 任务控制块指针 */
				
	xTaskCreate((TaskFunction_t)app_task_4,			/* 任务入口函数 */
				(const char *)"app_task_4",			/* 任务名字 */
				(uint16_t)512,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)7,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_4_handle); /* 任务控制块指针 */
				
	xTaskCreate((TaskFunction_t)app_task_5,			/* 任务入口函数 */
				(const char *)"app_task_5",			/* 任务名字 */
				(uint16_t)2048,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)7,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_5_handle); /* 任务控制块指针 */
				
	xTaskCreate((TaskFunction_t)app_task_6,			/* 任务入口函数 */
				(const char *)"app_task_6",			/* 任务名字 */
				(uint16_t)512,							/* 任务栈大小 */
				(void *)NULL,							/* 任务入口函数参数 */
				(UBaseType_t)6,							/* 任务的优先级 */
				(TaskHandle_t *)&app_task_6_handle); /* 任务控制块指针 */
	
	taskEXIT_CRITICAL();

	
	/* 删除任务自身 */
	vTaskDelete(NULL);
	
}


void app_task_1(void *pvParameters)
{
	uint8_t key_num = 0;
    uint8_t day = 0;
	while(1)
	{
		//任务1进行天气切换和更新
		//printf("task 1 \r\n");
		
		key_num = key_scan();
		if(key_num == 1)        //切换天气
        {
			taskENTER_CRITICAL();  //进入临界区
            day++;
            day %= 3;
            show_weather(day);
			delay_ms(3000);
			taskEXIT_CRITICAL();  //退出临界区
        }
        else if(key_num == 2)   //更新天气
        {
			taskENTER_CRITICAL();  //进入临界区
            printf("更新天气...\r\n");
            get_3days_weather();
            show_weather(0);
            day = 0;
			taskEXIT_CRITICAL();  //退出临界区
        }
		else if(key_num == 3)   // 按键3: 切换到注册模式
		{
			taskENTER_CRITICAL();  //进入临界区
			g_mode = MODE_REGISTER;
			printf("按键3按下，切换到注册模式\r\n");
			// 添加OLED显示当前模式
			oled_fill(0x00);
			oled_show_string(0, 0, "Mode: Register",16);
			taskEXIT_CRITICAL();  //退出临界区
		}
		// 在app_task_1的按键4处理中添加
		else if(key_num == 4)   // 按键4: 清空所有卡
		{
			taskENTER_CRITICAL();  //进入临界区
			g_mode = MODE_CLEAR;
			printf("按键4按下，准备清空所有卡号\r\n");
			// 添加OLED显示当前模式
			oled_fill(0x00);
			oled_show_string(0, 0, "Mode: Clear",16);
			taskEXIT_CRITICAL();  //退出临界区
		}
		
		vTaskDelay(100);
	}
	
}


void app_task_2(void *pvParameters)
{
	static uint32_t last_trigger_time = 0;
	static uint32_t last_vibrate_time = 0;   // 震动传感器上次触发时间
	int dis = 0;
	while(1)
	{
		//任务2进行红外线传感器和超声波检测
		//printf("task 2 \r\n");
		dis = get_distance();
		//printf("%d\r\n",dis);
		
		if(ia_flag_get() == TRUE || (dis <= 10) && (xTaskGetTickCount() - last_trigger_time) > 2000 )  // 2秒内不重复触发
		{
			 // 使用互斥锁保护OLED显示
            if(xSemaphoreTake(oled_mutex, pdMS_TO_TICKS(10)) == pdTRUE) {
			//显示打印欢迎回家
			oled_fill(0x00);
			oled_show_chinese(32, 3, 13);
			oled_show_chinese(48, 3, 14);
			oled_show_chinese(64, 3, 15);
			oled_show_chinese(80, 3, 16);
			delay_ms (500);
			ia_flag_set (FALSE);
			last_trigger_time = xTaskGetTickCount();  // 记录触发时间
			show_weather(0);
			
				
			xSemaphoreGive(oled_mutex);
				
			}
		}
		if (vibrate_flag_get () == TRUE_VIBRATE && (xTaskGetTickCount() - last_vibrate_time) > 2000) // 2秒内不重复触发
		{
			
			// 使用互斥锁保护震动警鸣
            if(xSemaphoreTake(vibrate_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
			printf("beep \r\n");
			play_middle_notes_once();  // 震动触发后播放音乐
			vibrate_flag_set (FALSE_VIBRATE);
			last_vibrate_time = xTaskGetTickCount();  // 记录震动触发时间
				
			xSemaphoreGive(vibrate_mutex);
			}
		}

		vTaskDelay(100);
	}
}

void app_task_3(void *pvParameters)
{
	
	 char card_line1[20], card_line2[20];
	uint8_t status;
	uint8_t i;
	uint8_t verify_success = 0;
	
	printf("卡管理任务启动\r\n");
	
	
	while(1)
	{
		//任务3进行读卡器检测
		//printf("task 3 \r\n");
		
			// 处理清空模式
		if (g_mode == MODE_CLEAR) {
			BEEP_ON;
			delay_ms(50);
			BEEP_OFF;
			printf("进入清空模式，正在删除所有卡号...\r\n");
			
			// 擦除存储区域所在的扇区
			w25q128_erase_sector(CARD_ADDR);
			
			// 确认清空完成
			printf("所有卡号已清空\r\n");
			
			oled_show_string(0, 2, "Empty ok",16);
			g_mode = MODE_VERIFY;  // 回到验证模式
			oled_fill(0x00);
			oled_show_string(0, 0, "Mode: verify ",16);
			vTaskDelay(1000);
			continue;
		}
		
		// 显示当前模式
		printf("当前模式: %d (0=验证, 1=注册)\r\n", g_mode);
		
		// 初始化RC522
		MF522_Init();
		
		// 1. 请求卡片
		status = MFRC522_Request(PICC_REQALL, card_type);
		if(status != MI_OK){
			printf("未检测到卡片...\r\n");
			vTaskDelay(1000);
			continue;
		}
		
		// 2. 防碰撞检测（获取卡号）
		status = MFRC522_Anticoll(card_id);
		if(status != MI_OK){
			printf("防碰撞失败!\r\n");
			vTaskDelay(1000);
			continue;
		}
		
		MFRC522_SelectTag(card_id);
		
		   // 第一行显示前4字节
		sprintf(card_line1, "ID:%02X%02X%02X%02X", 
            card_id[1], card_id[2], card_id[3], card_id[4]);
    
		// 第二行显示最后一字节
		sprintf(card_line2, "%02X", card_id[5]);
		
		// 显示卡号（包含校验位）
		printf("检测到卡号: %02X%02X%02X%02X%02X\r\n",
			   card_id[1], card_id[2], card_id[3], card_id[4], card_id[5]);
		
		// 3. 处理验证模式
		if(g_mode == MODE_VERIFY) {
		verify_success = 0;
		printf("进入验证模式...\r\n");
		
		// 遍历所有可能的存储位置（而非遇到空位置就提前退出）
		for(i = 0; i < CARD_NUM; i++) {  // 注意：这里删除了"if(record_card[0] != 0x55) break;"
			w25q128_read_data(CARD_ADDR + i * CARD_SIZE, record_card, CARD_SIZE);
			
			if(record_card[0] == 0x55 && 
			   memcmp(record_card + 1, card_id + 1, 5) == 0) {
				verify_success = 1;
				break;
			}
		}
			// 验证结果处理
			if(verify_success) {
				printf("验证成功！该卡已注册\r\n");
//				BEEP_ON;
//				delay_ms(100);
//				BEEP_OFF;
//				
				//开锁
				taskENTER_CRITICAL();  //进入临界区
//				lock_on ();
//				delay_ms(1500);
//				lock_off ();
				safe_unlock();
				oled_fill(0x00);
				oled_show_string(0, 0, "Card: ID",16);
				oled_show_string(0, 2, card_line1, 16);  // 显示: IDF58E0528
				oled_show_string(0, 4, card_line2, 16);  // 显示: 00		   
				oled_show_chinese(32, 5, 13);
				oled_show_chinese(48, 5, 14);
				oled_show_chinese(64, 5, 15);
				oled_show_chinese(80, 5, 16);
				delay_ms (500);
				
				 // 读卡通过后，舵机从0度运动到120度
                sg90_angle_set(0);    // 先复位到0度
                delay_ms(500);        // 等待舵机到位
                sg90_angle_set(140);  // 转动到140度
                delay_ms(500);       // 等待舵机到位
				
				taskEXIT_CRITICAL();  //退出临界区
				
				
			} else {
				printf("验证失败！该卡未注册\r\n");
				BEEP_ON;
				delay_ms(1000);
				BEEP_OFF;
			}
		}
		// 4. 处理注册模式
		else if(g_mode == MODE_REGISTER) {
			printf("进入注册模式...\r\n");
			uint8_t registered = 0;
			uint8_t empty_index = 0xFF;
			
			// 查找空位置和检查是否已注册
			for(i = 0; i < CARD_NUM; i++) {
				w25q128_read_data(CARD_ADDR + i * CARD_SIZE, record_card, CARD_SIZE);
				
				// 检查是否已注册
				if(record_card[0] == 0x55 && 
				   memcmp(record_card + 1, card_id + 1, 5) == 0) {
					registered = 1;
					break;
				}
				
				// 记录第一个空位置
				if(record_card[0] != 0x55 && empty_index == 0xFF) {
					empty_index = i;
				}
			}
			
			// 处理注册逻辑
			if(registered) {
				printf("注册失败！该卡已注册\r\n");
				// 双重蜂鸣提示已注册
				BEEP_ON;
				delay_ms(1000);
				BEEP_OFF;
				delay_ms(500);
				BEEP_ON;
				delay_ms(1000);
				BEEP_OFF;
			} else if(empty_index != 0xFF) {
				// 添加前缀并写入Flash
				card_id[0] = 0x55;  // 设置前缀
				w25q128_write_page(CARD_ADDR + empty_index * CARD_SIZE, card_id, CARD_SIZE);
				printf("注册成功！已保存卡号\r\n");
				
				oled_show_string(0, 2, "Register ok",16);
				oled_fill(0x00);
				oled_show_string(0, 0, "Mode: verify ",16);
				
				// 短声提示成功
				BEEP_ON;
				delay_ms(100);
				BEEP_OFF;
				delay_ms(100);
				BEEP_ON;
				delay_ms(100);
				BEEP_OFF;
			} else {
				printf("注册失败！已达到最大注册数量(%d张)\r\n", CARD_NUM);
				oled_show_string(0, 2, "Register fault",16);
				BEEP_ON;
				delay_ms(3000);
				BEEP_OFF;
			}
			
			// 注册完成后返回验证模式
			g_mode = MODE_VERIFY;
		}
		
		
		
		vTaskDelay(100);
	}
}

void app_task_4(void *pvParameters)
{
	//任务4进行蓝牙接收数据
	printf("task 4 \r\n");
	//使用消息队列，就是这边一直等待开锁的消息
	usart_rx_buf task_rx_buf;  //结构体
	 char ascii_buf[64];  // ASCII缓冲区
	
	while(1)
	{
		//接收消息
		xQueueReceive(usart_queue, &task_rx_buf, portMAX_DELAY);
		
	      // 编码转换：UTF-8 转 ASCII（简单版本）
        int j = 0;
        for(int i = 0; i < strlen((char*)task_rx_buf.uart_buf) && j < sizeof(ascii_buf)-1; i++) {
            // UTF-8 英文字符：第一个字节 < 0x80
            if((task_rx_buf.uart_buf[i] & 0x80) == 0) {
                ascii_buf[j++] = task_rx_buf.uart_buf[i];
            }
            // 忽略UTF-8多字节字符的其他字节
        }
        ascii_buf[j] = '\0';
        
        printf("原始数据: ");
        for(int i = 0; i < strlen((char*)task_rx_buf.uart_buf); i++) {
            printf("%02X ", task_rx_buf.uart_buf[i]);
        }
        printf("\r\n");
        printf("转换后: %s\r\n", ascii_buf);
        
        // 使用转换后的ASCII缓冲区进行比较
        if(strstr(ascii_buf, "ledon")){
            printf("LED ON命令!\r\n");
            PFout(10) = 0;
        }
        else if(strstr(ascii_buf, "ledoff")){
            printf("LED OFF命令!\r\n");
            PFout(10) = 1;
        }
		else if(strstr(ascii_buf, "open_clok")){
			//开锁
				taskENTER_CRITICAL();  //进入临界区
//				lock_on ();
//				delay_ms(1500);
//				lock_off ();
			    safe_unlock();
				oled_fill(0x00);			   
				oled_show_chinese(32, 4, 13);
				oled_show_chinese(48, 4, 14);
				oled_show_chinese(64, 4, 15);
				oled_show_chinese(80, 4, 16);
				delay_ms (500);
				
				 // 读卡通过后，舵机从0度运动到120度
                sg90_angle_set(0);    // 先复位到0度
                delay_ms(500);        // 等待舵机到位
                sg90_angle_set(140);  // 转动到140度
                delay_ms(500);       // 等待舵机到位
				
				taskEXIT_CRITICAL();  //退出临界区
		}
		else if(strstr((char *)task_rx_buf.uart_buf,"weather")){
			show_weather(0);
		}
		else{
			printf("unknow command!\n");
		}
		
		vTaskDelay(100);
	}
}

void app_task_5(void *pvParameters)
{
	
	   printf("=== LVGL任务开始 ===\r\n");
	
// 初始化lvgl
    lv_init();

    // 初始化lvgl显示设备
    lv_port_disp_init();

    // 初始化lvgl输入设备
    lv_port_indev_init();

//如果启动后触摸屏没反应，可以重新校准一下
#if 0
	LCD_Clear(WHITE);                               //清屏
	TP_Adjust();                                    //屏幕校准 
	TP_Save_Adjdata();
#endif
	
    // 初始化lvgl demo
	ui_init();
 
	
	//timer3_init();

	printf("app start!\r\n");
	
	
	while(1){
		tp_dev.scan(0);
		// LVGL处理 - 非阻塞方式获取锁
        if(xSemaphoreTake(oled_mutex, 0) == pdTRUE) {
            lv_task_handler();
            xSemaphoreGive(oled_mutex);
        } else {
            // 获取不到锁时，仍然处理LVGL但不阻塞
            // 这样触摸仍然可以响应，只是显示更新可能延迟
            lv_task_handler();
        }
		vTaskDelay(5);
	}	
}

void app_task_6(void *pvParameters)
{
	 static uint32_t last_433m_time = 0;
	
	while(1){
		
		//获取信号量
		xSemaphoreTake(lock_433m_sem_exit,portMAX_DELAY);
		
		 // 检查时间间隔
        uint32_t current_time = xTaskGetTickCount();
        if((current_time - last_433m_time) < pdMS_TO_TICKS(2000)) {
            printf("433M信号重复触发，忽略本次操作\r\n");
            continue; // 跳过本次处理
        }
		
		// 更新最后触发时间
        last_433m_time = current_time;
		//处理开锁
		taskENTER_CRITICAL();  //进入临界区
		
		printf("433M signal received, unlocking...\r\n");
		
		// 执行开锁操作
//		lock_on();
//		delay_ms(1500);
//		lock_off();
		safe_unlock();
		
		// OLED显示开锁信息
		oled_fill(0x00);
		oled_show_chinese(32, 4, 13);  // 欢
		oled_show_chinese(48, 4, 14);  // 迎
		oled_show_chinese(64, 4, 15);  // 回
		oled_show_chinese(80, 4, 16);  // 家
		
		// 舵机控制
		sg90_angle_set(0);    // 先复位到0度
		delay_ms(500);        // 等待舵机到位
		sg90_angle_set(140);  // 转动到140度
		delay_ms(500);        // 等待舵机到位
		
		taskEXIT_CRITICAL();  //退出临界区
		
		vTaskDelay(100);
	}
}


//心跳回调函数
void vApplicationTickHook(void)
{
    lv_tick_inc(1);
}
